#!/usr/bin/env python
#-*- coding: utf-8 -*-


# PacoDbg - an advanced RCE analysis debugger
# Copyright (C) 2013 The PacoDbg contributers

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


__all__ = ["init_configs",
           "Configuration"]


import os
from logging import debug, info, warning, error, critical
from shutil import copyfile

import staticconf


BASE_CONFIG_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'conf'))


class ConfigurationError(StandardError):
    pass


class Configuration(object):
    pacodbg_conf = 'pacodbg.conf'
    
    def __new__(cls, config_path, arg_options=None, base_config_path=BASE_CONFIG_PATH):
        cls._config_path = config_path
        cls._base_config_path = base_config_path
        cls._arg_options = arg_options
        
        cls._init()
        
        return staticconf
    
    @classmethod
    def _init(cls):
        cls._init_config_path(cls._config_path, cls._base_config_path)
        cls._init_config_file(cls._config_path, cls._base_config_path, cls.pacodbg_conf)
        
        ## Get from config file
        staticconf.INIConfiguration(os.path.join(cls._config_path, cls.pacodbg_conf))
        
        ## Override with command line if any
        if(cls._arg_options):
            try:
                staticconf.ListConfiguration(cls._arg_options)
            except Exception, err:
                warning("Configuration options would not be taken becauese of wrong format in one or more items")
        
        ## Reload staticconf
        staticconf.reload(all_names=True)
    
    @classmethod
    def _init_config_path(cls, config_path, base_config_path):
        if(not os.path.exists(config_path)):
            try:
                os.mkdir(config_path)
            except Exception, err:
                raise ConfigurationError("Could not create configuration path %s: %s" % (config_path, str(err)))
        elif(not os.path.isdir(config_path)):
            raise ConfigurationError("%s already exists and could not be loaded from" % config_path)
    
    @classmethod
    def _init_config_file(cls, config_path, base_config_path, config_file):
        conf_path = os.path.join(config_path, config_file)
        base_conf_path = os.path.join(base_config_path, config_file)
        if(not os.path.exists(conf_path)):
            try:
                copyfile(base_conf_path, conf_path)
            except Exception, err:
                raise ConfigurationError("Could not copy %s to %s: %s" % (base_conf_path, conf_path, str(err)))
        elif(not os.path.isfile(conf_path)):
            raise ConfigurationError("%s is not a file" % conf_path)


CONFIG_DIR = ".pacodbg"


def init_configs(arg_options=None):
    config_path = os.path.join(os.path.expanduser("~"), CONFIG_DIR)
    
    return Configuration(config_path, arg_options)
